//
//
//
//
//
// Node.C
// 2011/08/29 @CieNET

#include "common.h"
#include "Node.h"
#include "Node.h"
#include "Exception.h"
#include "StrStream.h"

namespace TinyXML
{
	Node::Node(std::string id, std::string name, std::string context)
		: _ID(id), _name(name), _context(context), _bEnd(false)
	{
		// _parent is NULL, this Node is root node
		_parent = NULL;
		_properties = NULL;
		_rightSibling = _childs = NULL;
	}

	Node::Node(std::string id, std::string name, std::string context, Properties* property) :
		_ID(id), _name(name), _context(context), _bEnd(false)
	{
		// _parent is NULL, this Node is root node
		 _parent = NULL;
		 _properties = NULL;
		  _rightSibling = _childs = NULL;
	}

	Node::~Node(){}
	Node* Node::GetNextSibling(void)
	{
		return _rightSibling;
	}

	void Node::SetEnd(const std::string& name)
	{
		if(name != GetName())
		{
			Util::StrStream str;
			str << "Node Name not match,"
				<< GetName()
				<< ", Get:" 
				<< name;
			throw Exception(str);
		}
		_bEnd = true;
	}

	void Node::SetProperties(Properties* perperty)
	{
		if(NULL == perperty)
			throw Exception("NULL Properties");
		delete _properties;
		_properties = perperty;
	}

	bool Node::ExpectChildren(void)
	{
		return !_bEnd;
	}

	 std::string Node::GetName(void) const
	 {
		 return _name;
	 }

	 std::string Node::GetID(void) const
	 {
		 return _ID;
	 }

	 std::string Node::GetContext() const
	 {
		 return _context;
	 }

	 std::string Node::GetContext(std::string& out) const
	 {
		 out = _context;
		 return out;
	 }

	 //
	 // when we already have childs, add to the end of child list
	 //
	 Node* Node::AddChild(Node* child)
	 {
		if(NULL == child)	
			throw Exception("NULL parameter when AddChild");
		if(_childs != NULL)
		{
			Node* ptr = _childs;
			Node* pre = _childs;
			while(ptr)
			{
				pre = ptr;
				ptr = ptr->_rightSibling;
			}
			pre->_rightSibling = child;
			return _childs;
		}
		_childs = child;
		return _childs;
	 }

	 Node* Node::AddNextSibling(Node* node)
	 {
		if(NULL == node)
			throw Exception("NULL parameter when AddNextSibling");
		if(_rightSibling != NULL)
			throw Exception("_rightSibling alread set");
		_rightSibling = node;
		return _rightSibling;
	 }

	 Node* Node::AddParent(Node* node)
	 {
		 if(NULL == node)
			 throw Exception("NULL parameter when AddParent");
		 if(_parent != NULL)
			 throw Exception("_parent already set");
		 _parent = node;
		 return _parent;
	 }

	 Node* Node::GetChild(void)
	 {
		 return _childs;
	 }

	 std::string Node::GetNodeStart(void) const
	 {
		std::string ret = "<";
		ret += _name;
		ret += ">";
		return ret;
	 }


	 std::string Node::GetNodeEnd(void) const
	 {
		std::string ret = "</";
		ret += _name;
		ret += ">";
		return ret;
	 }

	 std::string& Node::GetName(void)
	 {
		 return _name;
	 }

	 std::string& Node::GetContext(void)
	 {
		 return _context;
	 }
};
